using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;

namespace lang_benchmarks
{

    class PropertyObject
    {
        public PropertyObject()
        {
            secret_property = 1;
        }
        public int secret_property;
        public int property { get { return secret_property; } set { secret_property = value; } }
    }

    interface IPropertyMapper
    {
        int get(PropertyObject p);
    };

    class PropertyMapper : IPropertyMapper
    {
        public int get(PropertyObject p)
        {
            return p.secret_property;
        }
        public static int sget(PropertyObject p)
        {
            return p.secret_property;
        }
    };

    [TestFixture]
    public class PropertyMappingTest
    {
        static int direct_get(PropertyObject[] otab)
        {
            int sum = 0;
            foreach (PropertyObject o in otab)
                sum += o.secret_property;
            return sum;
        }
        static int property_get(PropertyObject[] otab)
        {
            int sum = 0;
            foreach (PropertyObject o in otab)
                sum += o.property;
            return sum;
        }
        static int generics_get<Mapper>(PropertyObject[] otab, Mapper m)
            where Mapper : IPropertyMapper
        {
            int sum = 0;
            foreach (PropertyObject o in otab)
                sum += m.get(o);
            return sum;
        }
        static int interface_get(PropertyObject[] otab, IPropertyMapper m)
        {
            int sum = 0;
            foreach (PropertyObject o in otab)
                sum += m.get(o);
            return sum;
        }
        delegate int Mapper_delegate(PropertyObject o);
        static int delegate_get(PropertyObject[] otab, Mapper_delegate m)
        {
            int sum = 0;
            foreach (PropertyObject o in otab)
                sum += m(o);
            return sum;
        }
        [Test]
        public void Maint()
        {
#if(DEBUG)
        Console.WriteLine("Warning: Benchmarking in debug mode will not produce meaningful results!");
#endif
            int n = 100000, nn = 1000;
            PropertyObject[] otab = new PropertyObject[n];
            for (int i = 0; i < n; i++)
            {
                otab[i] = new PropertyObject();
                otab[i].secret_property = i % 100;
            }


            DateTime t0 = DateTime.Now;
            for (int i = 0; i < nn; i++)
                direct_get(otab);
            Console.WriteLine("Direct get test:\t{0}", (DateTime.Now - t0));

            t0 = DateTime.Now;
            for (int i = 0; i < nn; i++)
                property_get(otab);
            Console.WriteLine("Property get test:\t{0}", (DateTime.Now - t0));

            t0 = DateTime.Now;
            PropertyMapper m = new PropertyMapper();
            for (int i = 0; i < nn; i++)
                generics_get(otab, m);
            Console.WriteLine("Generics get test:\t{0}", (DateTime.Now - t0));

            t0 = DateTime.Now;
            for (int i = 0; i < nn; i++)
                interface_get(otab, m);
            Console.WriteLine("Interface get test:\t{0}", (DateTime.Now - t0));

            t0 = DateTime.Now;
            for (int i = 0; i < nn; i++)
                delegate_get(otab, PropertyMapper.sget);
            Console.WriteLine("Delegate get test:\t{0}", (DateTime.Now - t0));

            t0 = DateTime.Now;
            for (int i = 0; i < nn; i++)
                delegate_get(otab, delegate(PropertyObject o) { return o.secret_property; });
            Console.WriteLine("Anon. Delegate get test:\t{0}", (DateTime.Now - t0));
        }
    }
}